from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError

from web import models
from django.conf import settings
import random

from web.forms.bootstrap import BootStrap


class RegisterModelForm(BootStrap, forms.ModelForm):

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request
        # # name：字段名称 field：类型对象（CharField（））
        # for name, field in self.fields.items():
        #     field.widget.attrs['class'] = 'form-control'
        #     field.widget.attrs['placeholder'] = '请输入%s' % (field.label,)

    # 添加正则表达式的校验
    mobile_phone = forms.CharField(label='手机号',
                                   # 第一个参数为正则表达式 ，第二个参数为报错信息
                                   validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])
    # 修改密码的默认显示
    password = forms.CharField(
        label='密码',
        # 设置插件：使用密文的方式进行显示 attrs={'class': 'form-control'}在生成表单的时候直接加上class样式
        # widget=forms.PasswordInput(attrs={'class': 'form-control'})
        widget=forms.PasswordInput(),

        # 设置最大最小以及错误信息提示
        min_length=8,
        max_length=64,
        error_messages={
            'min_length': "密码长度不能小于8个字符",
            'max_length': "密码长度不能大于64个字符"
        },

    )

    # 在数据库中不需要保存确认密码字段，需要自定义字段信息
    confirm_password = forms.CharField(
        label='重复密码',
        widget=forms.PasswordInput(),
        min_length=8,
        max_length=64,
        error_messages={
            'min_length': "重复密码长度不能小于8个字符",
            'max_length': "重复密码长度不能大于64个字符"
        },
    )

    code = forms.CharField(
        label='验证码',
        widget=forms.TextInput())

    # 使用钩子函数校验表单信息
    def clean_username(self):
        username = self.cleaned_data['username']
        exists = models.UserInfo.objects.filter(username=username).exists()
        if exists:
            raise ValidationError('用户名已存在')
            # self.add_error('username','用户名已存在')
        return username

    def clean_email(self):
        email = self.cleaned_data['email']
        exists = models.UserInfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('邮箱已存在')
        return email

    def clean_password(self):
        pwd = self.cleaned_data['password']
        # 加密 & 返回
        # return encrypt.md5(pwd)
        return pwd

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get('password')

        # 加密操作
        # confirm_pwd = encrypt.md5(self.cleaned_data['confirm_password'])
        confirm_pwd = self.cleaned_data['confirm_password']

        if pwd != confirm_pwd:
            raise ValidationError('两次密码不一致')

        return confirm_pwd

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exists:
            raise ValidationError('手机号已注册')
        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data['code']

        # mobile_phone = self.cleaned_data['mobile_phone']

        mobile_phone = self.cleaned_data.get('mobile_phone')
        if not mobile_phone:
            return code

        # conn = get_redis_connection()
        # redis_code = conn.get(mobile_phone)
        redis_code = self.request.session.get('code')  # 从session中获取验证码
        if not redis_code:
            raise ValidationError('验证码失效或未发送，请重新发送')

        # redis_str_code = redis_code.decode('utf-8')

        # if code.strip() != redis_code:
        if code != redis_code:
            raise ValidationError('验证码错误，请重新输入')

        return code

    class Meta:
        model = models.UserInfo
        # 生成所有字段
        # fields = '__all__'
        # 选择要生成表单的字段和顺序
        fields = ['username', 'email', 'password', 'confirm_password', 'mobile_phone', 'code']


class SendSmsForm(forms.Form):
    """发送短信表单验证"""
    mobile_phone = forms.CharField(
        label='手机号',
        validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式不正确'), ]
    )

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']

        # 判断模版是否存在
        tpl = self.request.GET.get('tpl')
        template_id = settings.TENCENT_SMS_TEMPLATE.get(tpl)
        if not template_id:
            raise ValidationError('模版不存在')
        # 手机号是否存在
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if tpl == 'login':
            if not exists:
                raise ValidationError('手机号不存在')
        else:
            if exists:
                raise ValidationError('手机已存在')
        # 生成验证码
        code = random.randrange(1000, 9999)
        print("验证码：" + str(code))

        self.request.session['code'] = str(code)
        self.request.session.set_expiry(60)

        return mobile_phone


class loginSmsForm(BootStrap, forms.Form):
    """短信登录表单"""
    mobile_phone = forms.CharField(
        label='手机号',
        validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式不正确'), ]
    )

    code = forms.CharField(
        label='验证码',
        widget=forms.TextInput())

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if not exists:
            raise ValidationError('手机号不存在')

        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data['code']
        mobile_phone = self.cleaned_data.get('mobile_phone')

        # 手机号不存在，则验证码无需再校验
        if not mobile_phone:
            return code

        session_code = self.request.session['code']  # 从session中获取验证码
        if not session_code:
            raise ValidationError('验证码失效或未发送，请重新发送')

        if code != session_code:
            raise ValidationError('验证码错误，请重新输入')

        return code


class loginForm(BootStrap, forms.Form):
    username = forms.CharField(label='邮箱或手机号')
    password = forms.CharField(
        label='密码',
        widget=forms.PasswordInput(render_value=True)
    )
    code = forms.CharField(label='图片验证码')

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_code(self):
        code = self.cleaned_data['code']
        session_code = self.request.session.get('image_code')
        if not session_code:
            raise ValidationError('验证码已过期，请重新输入')

        if code.strip().upper() != session_code.upper():
            raise ValidationError('验证码输入有误')
        return code
